package com.cysyz.web.modules.base.permission.service.impl;

import com.cysyz.mylib.dao.Conds;
import com.cysyz.mylib.utils.scanner.PackageScanner;
import com.cysyz.mylib.utils.xsvmaker.XsvMaker;
import com.cysyz.mylib.utils.xsvmaker.impl.CollectionValueGetter;
import com.cysyz.mylib.utils.xsvmaker.impl.XsvMakerImpl;
import com.cysyz.web.modules.base.permission.annotation.Module;
import com.cysyz.web.modules.base.permission.annotation.ModuleEntry;
import com.cysyz.web.modules.base.permission.annotation.ModuleFunction;
import com.cysyz.web.modules.base.permission.domain.SysPrivilege;
import com.cysyz.web.modules.base.permission.domain.SysRole;
import com.cysyz.web.modules.base.permission.domain.SysSysrolePrivilege;
import com.cysyz.web.modules.base.permission.domain.SysUserRole;
import com.cysyz.web.modules.base.permission.service.PrivilegeInitTool;
import com.cysyz.web.modules.base.permission.support.ModuleFunctionType;
import com.cysyz.web.modules.base.permission.support.PrivilegeType;
import com.cysyz.web.modules.base.support.controller.SpringMVCBaseController;
import com.cysyz.web.modules.base.support.service.BaseService;
import com.cysyz.web.modules.base.user.domain.SysUser;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 使用{@link PrivilegeInitToolImpl2}, 替代此类.
 */
@Deprecated
public class PrivilegeInitToolImpl extends BaseService implements PrivilegeInitTool {
    public PrivilegeInitToolImpl() {
    }

    @Override
    public void initAdminRole() {

    }

    @Override
    public void initAdminUser() {

    }

    @Override
    public void initGroupGroup() {

    }

    @Override
    public void initPrivilege(String... scanPackages) {
        List<SysPrivilege> allSysPrivilegesRepertory = this.list(SysPrivilege.class);



        //模块权限集合
        Set<SysPrivilege> modulePrivileges = new HashSet<SysPrivilege>();
        //所有被持久化了的模块权的集合
        Set<SysPrivilege> allSavedModulePrivileges = new HashSet<SysPrivilege>();
        //所有功能的集合
        Set<SysPrivilege> moduleFunctionPrivileges = new HashSet<SysPrivilege>();

        PackageScanner moduleScanner = new PackageScanner(scanPackages, Module.class);

        Set<Class<?>> moduleClasses = moduleScanner.scanClass();

        //List<RequestToMethodItem> requestToMethodItem = getRequestToMethodItem(servletContext);


        //取得所有的项目中的privilege
        getAllPrivilegeInProject(modulePrivileges, moduleFunctionPrivileges, moduleClasses);

        //取得所有已经持久化了的privilege

        //比较，如果有没有持久话的privilege，那么就持久化

        //为admin的用户绑定这些最新持久化的privilege

        Conds othersGroupGrouponds = new Conds();
        othersGroupGrouponds.addFilter("name", "其他");


        SysPrivilege othersGroupGroup = new SysPrivilege();
        //othersGroupGroup.setId(Long.MAX_VALUE);
        othersGroupGroup.setName("其他");
        othersGroupGroup.setCode("othersGroupGroup");
        othersGroupGroup.setType(PrivilegeType.PRIVILEGE_GROUP_GROUP);
        List<SysPrivilege> otherGroupGroupList = this.list(SysPrivilege.class, othersGroupGrouponds);
        if (otherGroupGroupList != null && !otherGroupGroupList.isEmpty()) {
        } else {
            this.save(othersGroupGroup);
        }


        //循环模块权限集合，把其中没有持久话的进行持久化。
        //把其中的所有元素放入到被持久化了的模块权的集合中
        for (SysPrivilege modulePrivilege : modulePrivileges) {
            boolean modulePrivilegeNotExists = true;
            modulePrivilege.setSysPrivilege(othersGroupGroup);
            if (allSysPrivilegesRepertory == null || allSysPrivilegesRepertory.isEmpty()) {
                this.save(modulePrivilege);
            } else {
                for (SysPrivilege sysPrivilegeRpertory : allSysPrivilegesRepertory) {
                    if (sysPrivilegeRpertory.equals(modulePrivilege)) {
                        modulePrivilege = sysPrivilegeRpertory;
                        modulePrivilegeNotExists = false;
                        break;
                    }
                }
                if (modulePrivilegeNotExists) {
                    this.save(modulePrivilege);
                }
            }
            allSavedModulePrivileges.add(modulePrivilege);
        }

        for (SysPrivilege moduleFunctionPrivilege : moduleFunctionPrivileges) {
            if (!allSysPrivilegesRepertory.contains(moduleFunctionPrivilege)) {
                for (SysPrivilege modulePrivilege : allSavedModulePrivileges) {
                    if (modulePrivilege.equals(moduleFunctionPrivilege.getSysPrivilege())) {
                        moduleFunctionPrivilege.setSysPrivilege(modulePrivilege);
                    }
                }
                this.save(moduleFunctionPrivilege);
            }
        }


        SysRole sysRole = new SysRole();
        sysRole.setName("管理员");
        sysRole.setCode("admin");

        List<SysPrivilege> permissionList = this.list(SysPrivilege.class);
        XsvMaker xsvMaker = new XsvMakerImpl();
        xsvMaker.collectionToXsv(SysPrivilege.class, permissionList, new CollectionValueGetter<SysPrivilege>() {
            @Override
            public String getValue(SysPrivilege object) {
                return object.getCode();
            }
        });

        sysRole.setPrivileges(xsvMaker.getResult());

        Conds roleConds = new Conds();
        roleConds.addFilter("code", "admin");
        List<SysRole> roleList = this.list(SysRole.class, roleConds);

        if(roleList == null || roleList.isEmpty()) {
            this.save(sysRole);
        } else {
            sysRole = roleList.get(0);
            sysRole.setPrivileges(xsvMaker.getResult());
            this.merge(SysRole.class, sysRole);
        }


        Conds sysSysrolePrivilegeConds = new Conds();
        sysSysrolePrivilegeConds.addFilter("sysRole", sysRole);
        List<SysSysrolePrivilege> sysSysrolePrivileges = this.list(SysSysrolePrivilege.class, sysSysrolePrivilegeConds);
        if (sysSysrolePrivileges == null || sysSysrolePrivileges.isEmpty()) {
            for (SysPrivilege sysPrivilege : permissionList) {
                SysSysrolePrivilege sysSysrolePrivilege = new SysSysrolePrivilege();
                sysSysrolePrivilege.setSysRole(sysRole);
                sysSysrolePrivilege.setSysPrivilege(sysPrivilege);
                this.save(sysSysrolePrivilege);
            }

        }

        SysUser sysUser = new SysUser();
        sysUser.setId(Long.MAX_VALUE);
        sysUser.setLoginName("admin");
        sysUser.setPassword("admin");

        Conds conds = new Conds();
        conds.addFilter("loginName", "admin");
        List<SysUser> list = this.list(SysUser.class, conds);
        if (list != null && !list.isEmpty()) {
            sysUser = list.get(0);
        } else {
            this.save(sysUser);
        }


        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setSysUser(sysUser);
        sysUserRole.setSysRole(sysRole);

        Conds sysUserRoleConds = new Conds();
        sysUserRoleConds.addFilter("sysUser", sysUser);
        sysUserRoleConds.addFilter("sysRole", sysRole);
        List<SysUserRole> SysUserRolelist = this.list(SysUserRole.class, sysUserRoleConds);
        if (SysUserRolelist != null && !SysUserRolelist.isEmpty()) {
        } else {
            this.save(sysUserRole);
        }


    }

    private void getAllPrivilegeInProject(Set<SysPrivilege> modulePrivileges, Set<SysPrivilege> moduleFunctionPrivileges, Set<Class<?>> moduleClasses) {
        for (Class<?> moduleClass : moduleClasses) {
            if (moduleClass.getSuperclass() != SpringMVCBaseController.class) {
                throw new RuntimeException("需要权限控制的类必须是一个继承SpringMVCBaseController的类");
            }

            String actionUrlPrefix = moduleClass.getAnnotation(RequestMapping.class).value()[0];


            Module moduleAnnotation = moduleClass.getAnnotation(Module.class);
            //每一个被@Module注释的类代表一个权限分组
            SysPrivilege modulePrivilege = new SysPrivilege();
            modulePrivilege.setName(moduleAnnotation.name());
            modulePrivilege.setType(PrivilegeType.PRIVILEGE_GROUP);
            Method[] declaredMethods = moduleClass.getDeclaredMethods();
            String moduleCode = null;
            for (Method methodOfModule : declaredMethods) {
                if (methodOfModule.isAnnotationPresent(ModuleEntry.class)) {
                    moduleCode = getPrivilegeCode(moduleAnnotation, methodOfModule);
                    RequestMapping requestMapping = methodOfModule.getAnnotation(RequestMapping.class);
                    modulePrivilege.setUrl(getUrl(actionUrlPrefix, requestMapping.value()[0]));
                    break;
                }
            }

            if (moduleCode == null) {
                throw new RuntimeException("the @Module annotationed class must has a @ModuleEntry annotationed method:[" + moduleClass + "]");
            }
            modulePrivilege.setCode(moduleCode);
            modulePrivileges.add(modulePrivilege);


            for (Method methodOfModule : declaredMethods) {
                if (methodOfModule.getName().endsWith("UI")) {
                    continue;
                }


                if (methodOfModule.isAnnotationPresent(ModuleFunction.class)) {

                    ModuleFunction moduleFunctionAnnotation = methodOfModule.getAnnotation(ModuleFunction.class);
                    RequestMapping requestMapping = methodOfModule.getAnnotation(RequestMapping.class);
                    SysPrivilege moduleFunctionPrivilege = new SysPrivilege();
                    moduleFunctionPrivilege.setName(moduleFunctionAnnotation.value());
                    moduleFunctionPrivilege.setSysPrivilege(modulePrivilege);
                    moduleFunctionPrivilege.setCode(getPrivilegeCode(moduleAnnotation, methodOfModule));
                    moduleFunctionPrivilege.setUrl(getUrl(actionUrlPrefix, requestMapping.value()[0]));

                    if (moduleFunctionAnnotation.moduleFunctionType() == ModuleFunctionType.NORMAL) {
                        moduleFunctionPrivilege.setType(PrivilegeType.NORMAL);
                    } else if (moduleFunctionAnnotation.moduleFunctionType() == ModuleFunctionType.MENU) {
                        moduleFunctionPrivilege.setType(PrivilegeType.MENU);
                    }
                    moduleFunctionPrivileges.add(moduleFunctionPrivilege);

                }
            }
        }
    }

    private String getUrl(String actionUrlPrefix, String methodUrl) {
        if (!methodUrl.endsWith(".do")) {
            methodUrl = methodUrl + ".do";
        }
        return actionUrlPrefix + methodUrl;
    }

    private String getPrivilegeCode(Module moduleAnnotation, Method methodOfModule) {
        return (moduleAnnotation.code() + "-" + methodOfModule.getName()).replaceAll("\\.", "_");
    }
}